package dev.ece.core.texture;

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;

import javax.imageio.ImageIO;

import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL13;
import org.lwjgl.opengl.GL20;

import dev.ece.core.clearup.ClearUpGLRubbish;
import dev.ece.core.clearup.ClearUpGLRubbishManager;
import dev.ece.util.tools.TextureLoader;
import dev.ece.util.tools.ploy.TextureCubeEdgePloy;
import dev.ece.util.tools.ploy.TexturePloy;

/**
 * 
 * 说明：纹理
 *
 * Texture.java
 *
 * @author DEVILIVED
 * 
 * 版本信息 v1.0
 * 
 * 2012-9-5
 *
 * 修改历史 
 *
 * Copyright 2012, DEVILIVED Inc.
 */
public class Texture implements ClearUpGLRubbish {
	
	private int texture;
	
	private int target;
	
	private int width;
	
	private int height;

	public Texture(int width, int height) {
		this(width, height, GL11.glGenTextures());
	}
	
	public Texture(int width, int height, int texture) {
		this(width, height, texture, GL11.GL_TEXTURE_2D);
	}
	
	public Texture(int width, int height, int texture, int target) {
		this.width = width;
		this.height = height;
		this.texture = texture;
		this.target = target;
	}

	/**
	 * 普通绑定
	 */
	public void bind() {
		GL11.glBindTexture(target, texture);
	}
	
	/**
	 * 绑定
	 * @return 纹理序号
	 */
	public int bind(int index) {
		GL13.glActiveTexture(GL13.GL_TEXTURE0 + index);
		GL11.glBindTexture(target, texture);
		return index;
	}
	/**
	 * 解除绑定
	 */
	public static void unbind() {
		GL11.glBindTexture(GL11.GL_TEXTURE_2D, 0);
		GL11.glBindTexture(GL20.GL_TEXTURE_CUBE_MAP, 0);
	}
	
	public final int getTexture() {
		return texture;
	}
	
	public int getWidth() {
		return width;
	}

	public int getHeight() {
		return height;
	}

	public void destroy() {
		ClearUpGLRubbishManager.push(this);
	}
	
	public static void glUnBindTexture(int target) {
		GL11.glBindTexture(target, 0);
	}
	
	public static Texture newInstance(BufferedImage image, TexturePloy textureStrategy) {
		return new Texture(image.getWidth(), image.getHeight(), TextureLoader.bindTextureImage(image, textureStrategy));
	}
	
	public static Texture newInstance(InputStream is, TexturePloy textureStrategy) {
		BufferedImage image = null;
		try {
			image = ImageIO.read(is);
			is.close();
			return newInstance(image, textureStrategy);
		} catch (IOException e) {
			e.printStackTrace();
		}
		return null;
	}
	
	public static Texture newInstance(String filename, TexturePloy textureStrategy) {
		return newInstance(new File(filename), textureStrategy);
	}
	
	public static Texture newInstance(File file, TexturePloy textureStrategy) {
		InputStream is;
		try {
			is = new FileInputStream(file);
			return newInstance(is, textureStrategy);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}
		return null;
	}
	
	public static Texture newCubeInstance(String[] filenames) {
		return newCubeInstance(filenames, TextureCubeEdgePloy.getInstance());
	}
	
	public static Texture newCubeInstance(File[] files) {
		return newCubeInstance(files, TextureCubeEdgePloy.getInstance());
	}
	
	public static Texture newCubeInstance(BufferedImage[] images) {
		return newCubeInstance(images, TextureCubeEdgePloy.getInstance());
	}
	
	public static Texture newCubeInstance(String[] filenames, TexturePloy textureStrategy) {
		try {
			return new Texture(0, 0, TextureLoader.loadTextureCubeMap(filenames, textureStrategy), GL20.GL_TEXTURE_CUBE_MAP);
		} catch (IOException e) {
			e.printStackTrace();
		}
		return null;
	}
	
	public static Texture newCubeInstance(File[] files, TexturePloy textureStrategy) {
		try {
			return new Texture(0, 0, TextureLoader.loadTextureCubeMap(files, textureStrategy), GL20.GL_TEXTURE_CUBE_MAP);
		} catch (IOException e) {
			e.printStackTrace();
		}
		return null;
	}
	
	public static Texture newCubeInstance(BufferedImage[] images, TexturePloy textureStrategy) {
		int texture = TextureLoader.bindTextureCubeImage(images, textureStrategy);
		return new Texture(0, 0, texture, GL20.GL_TEXTURE_CUBE_MAP);
	}

	@Override
	public void clearup() {
		GL11.glDeleteTextures(texture);
	}
}
